<?php

namespace app\common\library;

use alipay\aop\AopClient;
use alipay\aop\request\AlipayTradeAppPayRequest;
use app\common\controller\Api;
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Util\Signer;
use app\common\model\forest\Member;
use app\common\model\forest\Order as ForestOrder;
use app\common\model\MoneyLog;
use app\common\model\Order;
use app\common\model\order\Goods;
use app\common\model\product\Order as ProductOrder;
use app\common\model\ScoreLog;
use app\common\model\User;
use think\Db;
use think\Env;
use think\Log;
use wechatPay\Wxpay;

/**
 * 统一支付接口
 */
class Pay extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];
    public function __construct()
    {
        //1. 设置参数（全局只需设置一次）
        Factory::setOptions(getOptions());
    }
    /**
     * 支付宝支付
     *
     */
    public static function alipay($data)
    {
        if (Env::get('app.debug') == true) {
            $data['pay_money'] = 0.01;
        }

        $aop = new AopClient();
        $object['out_trade_no'] = $data['sn'];
        $object['total_amount'] = $data['pay_money'];
        $object['subject'] = $data['title'];

        $json = json_encode($object);
        $request = new AlipayTradeAppPayRequest();
        $request->setNotifyUrl(cdnurl('/api/notify/alipayNotify', true));
        $request->setBizContent($json);
        $result = $aop->sdkExecute($request);
        return $result;
    }
    /**
     * 回调
     */
    public function callback()
    {
        if (empty($_POST)) { //判断POST来的数组是否为空
            return false;
        }
        //        记录日志
        Log::info('记录日志:' . json_encode($_POST));
        //       验证
        $signer = new Signer();
        $check = $signer->verifyParams($_POST, config('pay.alipayPublicKey'));
        Log::info('验证结果:' . json_encode($check));

        //        $check = true;
        if ($check) {
            //商户订单号
            $out_trade_no = $_POST['out_trade_no'];
            //支付宝交易号
            $trade_no = $_POST['trade_no'];
            if ($_POST['trade_status'] == 'TRADE_FINISHED') {
                //判断该笔订单是否在商户网站中已经做过处理

                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                echo "success";       //请不要修改或删除
                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            } elseif ($_POST['trade_status'] == 'TRADE_SUCCESS') {
                //判断该笔订单是否在商户网站中已经做过处理

                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                echo "success";       //请不要修改或删除
            } else {
                Log::info('trade_status不存在:');
            }
        } else {
            //验证失败
            echo "fail";   //请不要修改或删除
        }
    }

    /**
     * 余额支付
     *
     */
    public static function yue($data)
    {
        $order =  Order::get(['sn' => $data['sn']]);
        $user = User::get($order->user_id);
        $totalMoney = bcadd($user->money, $user->no_withdraw, 2);
        if ($data['pay_money'] > $totalMoney) {
            exception('余额不足');
        }
        Db::startTrans();
        try {
            $str = substr($data['sn'], 0, 2);
            if ($str == 'GO') {
                if ($order && $order->status == '0') {
                    $user = User::get($order->user_id);
                    //首次下单获取19GR积分
                    $num = MoneyLog::where('source_type', 100)->where('user_id', $user->id)->count();
                    if (!$num) {
                        MoneyLog::income($user->id, 19, 2, 100, $data['sn']);
                    }
                    //普通商品购买获得等值得GS积分
                    ScoreLog::income($order->user_id, $order->pay_money, 2, 501, $data['sn']);

                    //糖友会员
                    if ($user->group_id == 0) {
                        $count = Goods::where('order_id', $order->id)->where('sugar_member', 1)->count();
                        if ($count > 0) {
                            $user->group_id = 1;
                        }
                    }
                    $order->save(['status' => '1',  'paytime' => time()], ['sn' => $data['sn']]);
                    $user->total_money = $user->total_money + $order->pay_money;
                    $user->save();
                }
            }
            if ($str == 'PO') {
                $order =  ProductOrder::get(['sn' => $data['sn']]);
                $user = User::get($order->user_id);
                if ($order && $order->status == '0') {
                    if ($user->leaf_level < $order->goods_id) {
                        $user->leaf_level = $order->goods_id;
                        if ($order->goods_id == 1) {
                            ScoreLog::income($order->user_id, 1000, 2, 600, $data['sn']);
                        }
                    }
                    $order->save(['status' => '1', 'paytime' => time()]);
                    User::leafcommission($order);
                }
                $user->total_money = $user->total_money + $order->price;
                $user->save();
                //检查用户产品会员是否升级
                User::nextlevel($order->user_id);
            }
            if ($str == 'FO') {
                $order =  ForestOrder::get(['sn' => $data['sn']]);
                if ($order && $order->status == '0') {
                    $user = User::get($order->user_id);
                    $forest_code = User::where('validitytime', '>', time())->order('forest_code desc')->value('forest_code');
                    if (!$forest_code) {
                        $user->forest_code = '30001';
                    } else {
                        $user->forest_code = (int) $forest_code + 1;
                    }
                    if ($user->forest_level < $order->goods_id || $user->validitytime < time()) {
                        $time = strtotime("+2 year");
                        $user->forest_level = $order->goods_id;
                        $user->validitytime = $time;
                        $member = Member::get($order->goods_id);
                        if ($order->plant == 0) {
                            ScoreLog::income($order->user_id, $member['price'], 2, 501, $data['sn']);
                            $user->total_money = $user->total_money + $member['price'];
                        } else {
                            MoneyLog::income($order->user_id, $member['price'], 2, 601, $data['sn'], 2);
                        }
                    }
                    $user->save();
                    $forest = new ForestOrder();
                    $forest->save(['status' => '1',  'paytime' => time()], ['sn' => $data['sn']]);
                }
            }
            if ($user->no_withdraw > $data['pay_money']) {
                MoneyLog::income($user->id, $data['pay_money'], 1, 400, $data['sn'], 1);
            } else {
                if ($user->no_withdraw > 0) {
                    $money = bcsub($data['pay_money'], $user->no_withdraw, 2);
                    MoneyLog::income($user->id, $user->no_withdraw, 1, 400, $data['sn'], 1);
                } else {
                    $money = $data['pay_money'];
                }
                if ($money > 0) {
                    MoneyLog::income($user->id, $money, 1, 401, $data['sn'], 0);
                }
            }
            //检查用户产品会员是否升级
            User::nextlevel($order->user_id);
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            exception($e->getMessage());
        }
        return true;
    }

    //微信app支付
    public static function wxpay($order,  $attach)
    {
        $out_trade_no = $order['sn'];
        $money = $order['pay_money'];
        if (empty($out_trade_no)) return json(['code' => 202, 'msg' => '缺少参数order_sn']);
        // 官方提供网址
        $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/app";
        $urlarr = parse_url($url); //拆解为：[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native]
        $time = time(); //时间戳
        $noncestr = Wxpay::getNonceStr();
        $appid = config('site.wx_appid'); //appID
        $mchid = config('site.mch_id'); //商户ID
        $xlid =  config('site.serial_no'); //证书序列号
        $data = array();
        $data['appid'] = $appid;
        $data['mchid'] = $mchid;
        $data['attach'] = $attach;
        $data['description'] = '商品描述'; //商品描述
        $data['out_trade_no'] = $out_trade_no; //订单编号，订单号在微信支付里是唯一的
        $data['notify_url'] =  cdnurl('/api/notify/wechatNotify', true); //需根据自己的情况修改回调接口，也可以为空
        $data['amount']['total'] = $money * 100; //金额 单位 分
        $data['scene_info']['payer_client_ip'] = $_SERVER["REMOTE_ADDR"];; //场景ip
        // $data['payer']['openid'] = $openid; //app支付不需要openid
        $data = json_encode($data);
        Log::write($data);

        //签名，包含了$data数据、微信指定地址、随机数和时间
        $key = Wxpay::getSign($data, $urlarr['path'], $noncestr, $time);
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $noncestr, $time, $key);
        //头部信息
        $header  = array(
            'Accept: application/json',
            'Content-Type: application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        );
        //向微信接口地址提交json格式的$data和header的头部信息，得到返回值
        $res = Wxpay::curl_post_https($url, $data, $header);
        $prepay_id = json_decode($res, true)['prepay_id'];


        $paySign = Wxpay::getWechartSign($appid, $time, $noncestr, $prepay_id);
        $payData = [
            'appid' => $appid,
            'partnerid' => $mchid,
            'prepayid' => $prepay_id,
            'package' => "Sign=WXPay",
            'noncestr' => $noncestr,
            'timestamp' => (string) $time,
            'sign' => $paySign
        ];
        return $payData;
    }

    //小程序下单
    public static function minipay($order, $attach = 'order')
    {
        $auth = Auth::instance();
        $out_trade_no = $order['sn'];
        $money = $order['pay_money'];
        if (empty($out_trade_no)) {
            exception('缺少参数order_sn');
        }
        // 官方提供网址
        $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
        $urlarr = parse_url($url); //拆解为：[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native]
        $time = time(); //时间戳
        $noncestr = Wxpay::getNonceStr();
        $appid = 'wxbc2b4463c34b0e81'; //appID
        $mchid = config('site.mch_id'); //商户ID
        $xlid =  config('site.serial_no'); //证书序列号
        $data = array();
        $data['appid'] = $appid;
        $data['mchid'] = $mchid;
        $data['attach'] = $attach;
        $data['description'] = '商品描述'; //商品描述
        $data['out_trade_no'] = $out_trade_no; //订单编号，订单号在微信支付里是唯一的
        $data['notify_url'] = cdnurl('/api/notify/wechatNotify', true); //需根据自己的情况修改回调接口，也可以为空
        $data['amount']['total'] = $money * 100; //金额 单位 分
        $data['scene_info']['payer_client_ip'] = $_SERVER["REMOTE_ADDR"];; //场景ip
        $data['payer']['openid'] = $auth->min_openid; //openid
        halt($data);
        $array = json_encode($data, JSON_UNESCAPED_UNICODE);
        //签名，包含了$data数据、微信指定地址、随机数和时间
        $key = Wxpay::getSign($array, $urlarr['path'], $noncestr, $time);
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $noncestr, $time, $key);
        //头部信息
        $header = array(
            'Accept: application/json',
            'Content-Type: application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        );
        $res = Wxpay::curl_post_https($url, $array, $header);
        halt(json_decode($res, true));
        $prepay_id = json_decode($res, true)['prepay_id'];
        $paySign = Wxpay::getWechartSign($appid, $time, $noncestr, 'prepay_id=' . $prepay_id);
        $payData = [
            'timeStamp' => (string) $time,
            'nonceStr' => $noncestr,
            'package' => 'prepay_id=' . $prepay_id,
            'signType' => 'RSA',
            'paySign' => $paySign
        ];
        return $payData;
    }
}
